<?php

namespace App\Models\System;

use App\Components\Admin\Menu;
use App\Components\Admin\Router;
use App\Components\Redis;
use Illuminate\Database\Eloquent\Model;

class SystemMenu extends Model
{
    protected $table = 'system_menu';

    public static function allMenu(): array
    {
        $cacheKey = 'MODELS:SYSTEM:SYSTEMMENU:ALLMENU';
        $cacheRs = Redis::get($cacheKey);
        if ($cacheRs !== false && $cacheRs !== null) {
            return json_decode($cacheRs, true);
        }

        $listRs = self::select(
            'id', 'pid', 'title', 'icon', 'color',
            'node', 'parameter', 'status'
        )->orderBy('orders', 'desc')
            ->orderBy('id', 'asc')->get()->toArray();
        $tree = [];
        nodeTree($listRs, $tree);
        unset($listRs);
        $tree = nodeTreeValue($tree);
        $tree = Menu::treeFilter($tree, 1);
        $tree = self::menuNodeToNull($tree);
        Redis::setex($cacheKey, Redis::mediumTime(), json_encode($tree));
        return $tree;
    }

    public static function clearAllMenuCache(): bool
    {
        $cacheKey = 'MODELS:SYSTEM:SYSTEMMENU:ALLMENU';
        Redis::del($cacheKey);
        return true;
    }

    public static function menuNodeToNull($tree): array
    {
        foreach ($tree as $k => $v) {
            if (isset($v['children'])) {
                $tree[$k]['children'] = self::menuNodeToNull($v['children']);
                $tree[$k]['node'] = '#';
                $tree[$k]['parameter'] = '';
            }
        }
        return $tree;
    }

    public static function userMenu(int $userId): array
    {
        $cacheKey = 'MODELS:SYSTEM:SYSTEMMENU:USERMENU:' . $userId;
        $cacheRs = Redis::get($cacheKey);
        if ($cacheRs !== false && $cacheRs !== null) {
            return json_decode($cacheRs, true);
        }

        $roleUserRs = SystemRoleUser::userRole($userId);
        if (!isset($roleUserRs[0])) {
            return [];
        }

        $node = [];
        foreach ($roleUserRs as $v) {
            $node = array_merge($node, SystemRole::node($v));
        }
        $node = array_values(array_unique($node));
        foreach ($node as $k => $v) {
            $v = explode(':', $v);
            if (!isset($v[1]) || isset($v[2])) {
                unset($node[$k]);
                continue;
            }
            $node[$k] = Router::ControllerToUriPath($v[0], $v[1]);
        }

        $menu = self::clearInvalidMenu($node, self::allMenu());
        Redis::setex($cacheKey, Redis::smallTime(2), json_encode($menu));
        return $menu;
    }

    private static function clearInvalidMenu($node, $tree): array
    {
        foreach ($tree as $k => $v) {
            unset($tree[$k]['pid'], $tree[$k]['status']);
            if (isset($v['children'])) {
                $tree[$k]['children'] = self::clearInvalidMenu($node, $v['children']);
                if (!isset($tree[$k]['children'][0])) {
                    unset($tree[$k]);
                    continue;
                }
            } else {
                if (!in_array($v['node'], $node)) {
                    unset($tree[$k]);
                    continue;
                }
            }
        }
        return array_values($tree);
    }
}
